
#include <bits/stdc++.h>
#include <memory>
using namespace std;

template<typename T>
class WeakPtr{
public:
    WeakPtr():m_data(nullptr),m_count(nullptr){}
    WeakPtr(const std::shared_ptr<T>& sp):m_data(sp.data),m_count(sp.use_count){}
    WeakPtr(const WeakPtr<T>& other):m_data(other.m_data),m_count(other.m_count){

    }
    WeakPtr(WeakPtr<T>&& other){
        m_data = other.m_datal;
        m_count = other.m_count;
        other.m_data = nullptr;
        other.m_count = nullptr;
    }
    ~WeakPtr(){
        m_data = nullptr;
        m_count = nullptr;
    }
    void reset(){
        m_data = nullptr;
        m_count = nullptr;
    }
    //判断是否过期
    bool expired() const{
        return !m_count || (*m_count) <= 0;
    }

    std::shared_ptr<T> lock() const{
        if(expired()){
            return std::shared_ptr<T>();
        }
        std::shared_ptr<T> sp;
        sp.m_data = m_data;
        sp.m_count = m_count;
        if(m_count != nullptr){
            (*m_count)++;
        }
        return sp;
    }

    void swap(WeakPtr<T>& other){
        auto data = other.m_data;
        other.m_data = m_data;
        m_data = data;
        auto count = other.m_count;
        other.m_count = m_count;
        m_count = count;
    }

    int use_count() const{
        if(m_data == nullptr){
            return 0;
        }
        return *m_count;
    }
    //将sharedptr赋值给weakptr引用计数不变
    WeakPtr& operator = (const std::shared_ptr<T>& sp){
        m_data = sp.data;
        m_count = sp.use_count;
        return *this;
    }
    WeakPtr& operator = (const WeakPtr<T>& other){
        if(this == &other){
            return *this;
        }
        m_data = sp.data;
        m_count = sp.use_count;
        return *this;
    }

    WeakPtr & operator = (WeakPtr<T>&& other){
        if(this == &other){
            return *this;
        }
        m_data = other.m_data;
        m_count = other.m_count;
        other.m_data = nullptr;
        other.m_count = nullptr;
        (*m_count)++;
        return *this;
    }

private:
    T* m_data;
    int* m_count;
};



class B;
class A{
public:
    A() = default;
    ~A(){
        cout<<"delete A()"<<endl;
    }
    void set_ptr(std::shared_ptr<B>& ptr){
        m_ptr_b = ptr;
    }
private:
    std::shared_ptr<B> m_ptr_b;
};

class B{
public:
    B() = default;
    ~B(){
        cout<<"delete B()"<<endl;
    }
    void set_ptr(std::shared_ptr<A>& ptr){
        m_ptr_a = ptr;
    }
private:
    std::shared_ptr<A> m_ptr_a;
};

class B2;
class A2{
public:
    A2() = default;
    ~A2(){
        cout<<"delete A2()"<<endl;
    }
    void set_ptr(std::shared_ptr<B2>& ptr){
        m_ptr_b = ptr;
    }
private:
    std::weak_ptr<B2> m_ptr_b;
};

class B2{
public:
    B2() = default;
    ~B2(){
        cout<<"delete B2()"<<endl;
    }
    void set_ptr(std::shared_ptr<A2>& ptr){
        m_ptr_a = ptr;
    }
private:
    std::weak_ptr<A2> m_ptr_a;
};

int main(){
#if 0
    std::shared_ptr<A> ptr_a(new A());
    std::shared_ptr<B> ptr_b(new B());
    ptr_a->set_ptr(ptr_b);
    ptr_b->set_ptr(ptr_a);
    std::cout << ptr_a.use_count() << " " << ptr_b.use_count() << std::endl;
    //print:2,2 未调用析构函数
#endif
#if 0
    std::shared_ptr<A2> ptr_a2(new A2());
    std::shared_ptr<B2> ptr_b2(new B2());
    ptr_a2->set_ptr(ptr_b2);
    ptr_b2->set_ptr(ptr_a2);
    std::cout << ptr_a2.use_count() << " " << ptr_b2.use_count() << std::endl;
    //print:1,1 delete B2() delete A2()
#endif
}